package com.axcbd.demo.mqtt;

import com.axcbd.demo.model.Acceleration;
import com.axcbd.demo.model.Humidity;
import com.axcbd.demo.model.Temperature;
import com.axcbd.demo.model.WaterLevel;
import com.axcbd.demo.service.AccelerationService;
import com.axcbd.demo.service.HumidityService;
import com.axcbd.demo.service.TemperatureService;
import com.axcbd.demo.service.WaterLevelService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class PushCallback implements MqttCallback {
    @Autowired
    private MqttConfiguration mqttConfiguration;

    @Autowired
    @Lazy
    private MqttPushClient mqttPushClient;


    @Autowired
    private WaterLevelService  waterLevelService;

    @Autowired
    private AccelerationService accelerationService;

    @Autowired
    private HumidityService humidityService;

    @Autowired
    private TemperatureService temperatureService;

    // 阈值设置
    private static final double GAS_THRESHOLD = 10;
    private static final double TEMPERATURE_THRESHOLD = 28.0;
    private static final double HUMIDITY_THRESHOLD = 70.0;
    private static final double RAIN_THRESHOLD = 0.7;
    private static final int LIGHT_THRESHOLD = 116;
    private static final int PEOPLE_THRESHOLD = 1952;
    private static final int DISTANCE_THRESHOLD = 5;
    // 状态管理
    private final ConcurrentHashMap<String, Boolean> sensorStates = new ConcurrentHashMap<>();

    @Override
    public void connectionLost(Throwable cause) {        // 连接丢失后，一般在这里面进行重连
        log.info("连接断开，正在重连");
        MqttPushClient mqttPushClient = mqttConfiguration.getMqttPushClient();
        if (null != mqttPushClient) {
            mqttPushClient.connect(mqttConfiguration.getHost(), mqttConfiguration.getClientid(), mqttConfiguration.getUsername(),
                    mqttConfiguration.getPassword(), mqttConfiguration.getTimeout(), mqttConfiguration.getKeepalive());
            log.info("已重连");
        }

    }

    /**
     * 发送消息，消息到达后处理方法
     * @param token
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {

    }

    /**
     * 订阅主题接收到消息处理方法
     * @param topic
     * @param message
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        // subscribe后得到的消息会执行到这里面,这里在控制台有输出
        log.info("Arrived Message Topic : " + topic);
        log.info("Arrived Message Qos : " + message.getQos());
        log.info("Arrived Message Content : " + new String(message.getPayload()));

        // 解析消息内容为 JSON
        try {
            String messageContent = new String(message.getPayload());
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> data = objectMapper.readValue(messageContent, Map.class);

            // 根据主题判断消息类型并处理
            switch (topic) {
                case "pet/report/temp-humi":
                    handleTempHumiMessage(data);
                    break;
                case "pet/report/mpu6050":
                    handleAccelerationMessage(data);
                    break;
                case "pet/report/waterlevel":
                    handleWaterLevelMessage(data);
                    break;
                    default:
                    log.info("unknown topic: " + topic);
            }
        } catch (Exception e) {
            log.error("Deal and jiexi message failed", e);
        }
    }

    /**
     * 处理温度和湿度消息
     * @param data 消息数据
     */
    private void handleTempHumiMessage(Map<String, Object> data) {
        try {
            double temperature = (double) data.get("temperature");
            double humidity = (double) data.get("humidity");

            Humidity humidityData= new Humidity();
            humidityData.setValue(humidity);
            humidityService.saveHumidity(humidityData);

            Temperature temperatureData = new Temperature();
            temperatureData.setValue(temperature);
            temperatureService.saveTemperature(temperatureData);

            if(temperature >= 30)
            {
                mqttPushClient.publish("pet/control","openfan");
                log.info("send fan open");
            }
            else if(temperature < 30)
            {
                //mqttPushClient.publish("pet/control","stopfan");
                log.info("send fan close");
            }

            boolean tempState = temperature > TEMPERATURE_THRESHOLD;


            sensorStates.put("temperature", tempState);

            boolean humiState = humidity > HUMIDITY_THRESHOLD;
            boolean previousHumiState = sensorStates.getOrDefault("humidity", false);

            // 这里只是示例，您可以根据需要添加湿度的处理逻辑
            sensorStates.put("humidity", humiState);
        } catch (Exception e) {
            log.error("Deal with temperature and humidity message failed", e);
        }
    }



    /**
     * 处理水位消息
     * @param data 消息数据
     */
    private void handleWaterLevelMessage(Map<String, Object> data) {
        try {
            int intwaterlevelData = (int) data.get("waterlevel");
            double waterLeveldata = (double)intwaterlevelData;
            WaterLevel waterLevel = new WaterLevel();
            waterLevel.setValue(waterLeveldata);
            waterLevelService.saveWaterLevel(waterLevel);
            if(waterLeveldata<200)
            {
                sendAddWaterMessage("addwater");
            }
            else if (waterLeveldata>220)
                {
                sendAddWaterMessage("stopaddwater");
                }

        } catch (Exception e) {
            log.error("Deal with WaterLevel message failed", e);
        }
    }



    /**
     * 处理加速度消息
     * @param data 消息数据
     */
    private void handleAccelerationMessage(Map<String, Object> data) {
        try {

            double X = (double) data.get("X");
            double Y = (double) data.get("Y");
            double Z = (double) data.get("Z");
            Acceleration acceleration = new Acceleration();
            acceleration.setX(X);
            acceleration.setY(Y);
            acceleration.setZ(Z);

            accelerationService.saveAcceleration(acceleration);

        } catch (Exception e) {
            log.error("Deal with Acceleration failed", e);
        }
    }


    /**
     * 处理雨量消息
     * @param data 消息数据
     */
    private void handleRainMessage(Map<String, Object> data) {
        try {
            String rainValue = data.get("rain").toString();
            double rain = Double.parseDouble(rainValue);

            boolean currentState = rain > RAIN_THRESHOLD;
            boolean previousState = sensorStates.getOrDefault("rain", false);

            if (currentState) {
                if (!previousState) {
                    // 状态从正常变为异常，发送“关闭窗帘”
                    sendWarningMessage("right");
                } else {
                    // 状态持续异常，继续发送“关闭窗帘”
                    sendWarningMessage("right");
                }
            } else {
                if (previousState) {
                    // 状态从异常变为正常，发送“打开窗帘”
                    sendRecoveryMessage("left");
                }
                // 状态持续正常，不发送消息
            }

            sensorStates.put("rain", currentState);
        } catch (Exception e) {
            log.error("Deal with rain message failed", e);
        }
    }


    /**
     * 发送警告消息
     * @param message 警告消息内容
     */
    private void sendWarningMessage(String message) {
        log.info("发送警告消息: {}", message);
        mqttPushClient.publish("smartroom/control", message);
    }

    /**
     * 发送恢复消息
     * @param message 恢复消息内容
     */
    private void sendRecoveryMessage(String message) {
        log.info("发送恢复消息: {}", message);
        mqttPushClient.publish("smartroom/control", message);
    }

    //发送添水数据
    private void sendAddWaterMessage(String message) {
        log.info("sendAddWaterMessage: {}", message);
        mqttPushClient.publish("pet/control", message);
    }
}